package com.kgcx.common.handler;

import com.kgcx.common.constant.Cons;
import com.kgcx.common.utils.CollectionUtils;
import com.kgcx.common.utils.ReflectHelper;
import io.swagger.annotations.ApiModel;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.stream.Stream;

/**
 * 拦截所有POST进来的json对象，自动填入updateTime和createTime,以及status
 *
 * @author 吴刚林
 * @date 2017/11/26
 */
@ControllerAdvice
public class TimeAndStatusGeneratorRequestBodyAdviceAdapter extends RequestBodyAdviceAdapter {
    private String[] updateTimeNames = {"updateTime", "update_time"};
    private String[] createTimeNames = {"createTime", "create_time"};
    private String statusName = "status";

    private static final String[] ADD_METHOD_NAME_PREFIX = {"add"};

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //拦截所有POST请求
        return request.getMethod().equalsIgnoreCase(HttpMethod.POST.toString());
    }


    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        setTime(body, parameter.getMethod().getName());
        return body;
    }

    private void setTime(Object body, String methodName) {
        Timestamp now = new Timestamp(System.currentTimeMillis());
        //自动填入updateTime
        setTime(body, now, updateTimeNames);
        //如果是add新增方法，自动填入createTime
        if (StringUtils.startsWithAny(methodName, ADD_METHOD_NAME_PREFIX)) {
            setTime(body, now, createTimeNames);
            setStatusActive(body);
        }
        Field[] declaredFields = body.getClass().getDeclaredFields();
        if (ArrayUtils.isNotEmpty(declaredFields)) {
            Stream.of(declaredFields)
                    .forEach(i -> {
                        Object fieldValue = ReflectHelper.getFieldValue(body, i.getName());
                        if (fieldValue instanceof Collection) {
                            Collection c = (Collection) fieldValue;
                            c.stream().forEach(k -> setTime(k, methodName));
                        } else if (i.getClass().isAnnotationPresent(ApiModel.class)) {
                            setTime(fieldValue, methodName);
                        }
                    });
        }
    }

    private void setTime(Object body, Timestamp now, String... fieldNames) {
        if (CollectionUtils.isEmptyNull(ReflectHelper.getFieldValue(body, fieldNames))) {
            ReflectHelper.setFieldValue(body, now, fieldNames);
        }
    }

    private void setStatusActive(Object body) {
        ReflectHelper.setFieldValue(body, statusName, Cons.COMMON_STATUS_ACTIVE);

    }

}
